/**
 * 项目名称（软件名称）：忠旺机械物资管理系统(mms)
 * 研发设计单位：忠旺机械设备制造有限公司机械设计院智能控制设计科设计与研发。
 * 版权所有：忠旺机械设备制造有限公司
 * 注：本项目的一切技术专利，使用规范归解释权由忠旺机械设备制造有限公司所有。
 * 软件版本：Ver 1.0.0
 * 文件路径：com.zhongwang.mms.module.purchase.service
 * 创建时间：2020年03月16日 14时06分
 **/
package com.zhongwang.mms.module.jiaGongStorage.service;

import com.zhongwang.mms.base.BaseService;
import com.zhongwang.mms.common.JsonResult;
import com.zhongwang.mms.gen.entity.*;
import com.zhongwang.mms.module.basic.dao.TCostDao;
import com.zhongwang.mms.module.basic.dao.TWarehouseInfoDao;
import com.zhongwang.mms.module.jiaGongStorage.dao.StorageInDao;
import com.zhongwang.mms.module.jiaGongStorage.dao.StorageOutDao;
import com.zhongwang.mms.module.jiaGongStorage.model.JOutStorage;
import com.zhongwang.mms.module.jiaGongStorage.model.JStorage;
import com.zhongwang.mms.module.jiaGongStorage.model.JStorageDetail;
import com.zhongwang.mms.module.jiaGongStorage.model.JStorageInventory;
import com.zhongwang.mms.module.purchase.constant.PurchaseConstant;
import com.zhongwang.mms.module.purchase.dao.*;
import com.zhongwang.mms.module.purchase.model.AllocationResaultModel;
import com.zhongwang.mms.module.purchase.model.PChangeOrderModel;
import com.zhongwang.mms.module.purchase.model.PInventoryModel;
import com.zhongwang.mms.module.purchase.model.POutOrder;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.util.ShiroUtils;
import com.zhongwang.mms.util.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName： PurWarInManageService
 * @Description： 入库单业务逻辑层
 * @Author： 徐一贺
 * @Date： 2020/3/16 14:06
 * @Version： V1.0
 **/
@Log4j2
@Service
public class StorageOutService extends BaseService {
    @Autowired
    private PurWarInManageDao purWarInManageDao;
    @Autowired
    private TWarehouseInfoDao tWarehouseInfoDao;
    @Autowired
    private PurPOrderDetailDao purPOrderDetailDao;
    @Autowired
    private PurPOrderDao purPOrderDao;
    @Autowired
    private PurPInventoryDao purPInventoryDao;
    @Autowired
    private LogService logService;
    @Autowired
    private PurTDeptDao purTDeptDao;
    @Autowired
    private PurSystemDao purSystemDao;
    @Autowired
    private PurChangeDao purChangeDao;
    @Autowired
    private TCostDao tCostDao;
    @Autowired
    private StorageOutDao storageOutDao;
    @Autowired
    private StorageInDao storageInDao;


    /**
     * @FunctionName: findLastPRKOrderCode
     * @Description: 获取入库编码数量
     * @Author: 徐一贺
     * @CreateDate: 2020/3/17 14:17
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Version:
     */
    public String findLastPRKOrderCode() {
        if (storageOutDao.findPRKOrderCodeCount() == 0) {
            return "";
        }
        return storageOutDao.findLastPRKOrderCode();
    }

    /**
     * @FunctionName: findLastPCKOrderCode
     * @Description: 获取最后出库的编码
     * @Author: 徐一贺
     * @CreateDate: 2020/3/17 14:17
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Version:
     */
    public String findLastPCKOrderCode() {
        return purWarInManageDao.findLastPCKOrderCode();
    }

    /**
     * @param orderCodeType
     * @FunctionName: getOrderCode
     * @Description: 获取最新的单据编码
     * @Author: 徐一贺
     * @CreateDate: 2020/3/23 7:55
     * @Phone: 18241927380
     * @Param: orderCodeType 单据编码类型 PRK是入库 PCK是出库
     * @Return: String 返回最新的编码
     * @Version: 1.0.0
     */
    public String getOrderCode(int orderCodeType) {
        String orderCode = "";
        if (orderCodeType == 4) {
            orderCode = generateJGOOrderCode();
        }
        return orderCode;
    }

    /**
     * @FunctionName: findLastPRKOrderCode
     * @Description: 获取最新出库单编码
     * @设计思路： 1.判断年后两位+月+日与当前年月日是否相同，如果相同且流水号则在流水号上递增1。
     * 2.如果数据为空则按照以PRK+年（后两位）月日+001生成外购件出库单编码。
     * 3.如果不相同则按照以PRK+年（后两位）月日+001生成外购件出库单编码。
     * @Author: 徐一贺
     * @CreateDate: 2020/3/17 14:22
     * @Phone: 18241927380
     * @Param:
     * @Return: String 最新出库单编码
     * @Version:
     */
    private String generateJGOOrderCode() {
        String newGeneratePRKOrderCode = "";
        //获取最后编码
        String lastPRKOrderCode = findLastPRKOrderCode();
        //获取当前时间简码
        String datetimeCode = new SimpleDateFormat("yyMMdd").format(new Date());
        Integer sn = 0;
        if (lastPRKOrderCode.length() > 0) {
            //获取外购件库最新最后的入库单号
            sn = Integer.parseInt(lastPRKOrderCode.substring(9));
        }
        if (lastPRKOrderCode.length() == 0) {
            newGeneratePRKOrderCode = "JGO" + new SimpleDateFormat("yyMMdd").format(new Date()) + "001";
        } else if (!lastPRKOrderCode.substring(3, 9).equals(datetimeCode)) {
            newGeneratePRKOrderCode = "JGO" + new SimpleDateFormat("yyMMdd").format(new Date()) + "001";
        } else {
            newGeneratePRKOrderCode = "JGO" + new SimpleDateFormat("yyMMdd").format(new Date()) + String.format("%03d", (sn + 1));
        }
        return newGeneratePRKOrderCode;
    }

    /**
     * @FunctionName: findLastPRKOrderCode
     * @Description: 获取最新出库单编码
     * @设计思路： 1.判断年后两位+月+日与当前年月日是否相同，如果相同且流水号则在流水号上递增1。
     * 2.如果数据为空则按照以PRK+年（后两位）月日+001生成外购件出库单编码。
     * 3.如果不相同则按照以PRK+年（后两位）月日+001生成外购件出库单编码。
     * @Author: 徐一贺
     * @CreateDate: 2020/3/17 14:22
     * @Phone: 18241927380
     * @Param:
     * @Return: String 最新出库单编码
     * @Version:
     */
    private String generatePCKOrderCode() {
        String newGeneratePRKOrderCode = "";
        //获取最后编码
        String lastPCKOrderCode = findLastPCKOrderCode();
        //获取当前时间简码
        String datetimeCode = new SimpleDateFormat("yyMMdd").format(new Date());
        if (lastPCKOrderCode == null) {
            newGeneratePRKOrderCode = "PCK" + new SimpleDateFormat("yyMMdd").format(new Date()) + "001";
        } else if (!lastPCKOrderCode.substring(3, 9).equals(datetimeCode)) {
            newGeneratePRKOrderCode = "PCK" + new SimpleDateFormat("yyMMdd").format(new Date()) + "001";
        } else {
            //获取外购件库最新最后的入库单号
            Integer sn = Integer.parseInt(lastPCKOrderCode.substring(9));
            newGeneratePRKOrderCode = "PCK" + new SimpleDateFormat("yyMMdd").format(new Date()) + String.format("%03d", (sn + 1)); //25为int型 ;
        }
        return newGeneratePRKOrderCode;
    }

    /**
     * @FunctionName: findDeptList
     * @Description: 获取部门列表
     * @Author: 徐一贺
     * @CreateDate: 2020-3-24 13:35:14
     * @Phone: 18241927380
     * @Param: []
     * @Return: com.zhongwang.mms.common.JsonResult
     * @Version: 1.0.0
     */
    public List<TDept> findDeptList() {
        TDept tDept = new TDept();
        tDept.setDepPid(9);
        TDeptExample tDeptExample = new TDeptExample();
        tDeptExample.or().andDepNameNotEqualTo("外厂").andDepStatusEqualTo(1);
        return purTDeptDao.selectByExample(tDeptExample);
    }

    /**
     * @FunctionName: findInventoryList
     * @Description: 根据条件查询库存信息
     * @Author: 徐一贺
     * @CreateDate: 2020/3/24 16:50
     * @Phone: 18241927380
     * @Param: param 查询参数
     * @Return: List<PInventory> 库存信息
     * @Version: 1.0.0
     */
    public List<JStorageInventory> findInventoryList(JStorageInventory param) {
        param.setSort(StringUtils.convertFieldToColumn(param.getSort()));
        //return purPInventoryDao.findInventoryList(param);
        return storageOutDao.findInventoryListByOut(param);
    }

    /**
     * @FunctionName: getCurrentDate
     * @Description: 获取数据库服务器当前日期
     * @Author: 徐一贺
     * @CreateDate: 2020/3/26 15:37
     * @Phone: 18241927380
     * @Return: String 数据库服务器当前日期
     * @Version: 1.0.0
     */
    public String getCurrentDate() {
        return purSystemDao.getCurrentDate();
    }

    /**
     * @FunctionName: findInventoryListByIds
     * @Description: 请填写方法描述
     * @Author: 徐一贺
     * @CreateDate: 2020/3/26 16:27
     * @Phone: 18241927380
     * @Param: ityIds
     * @Return: List<POrderDetail>
     * @Version: 1.0.0
     */
    public List<JStorageInventory> findInventoryListByIds(String ityIds) {
        return storageOutDao.findInventoryListByIds(ityIds);
    }

    /**
     * @FunctionName: createRequestMaterial
     * @Description: 领料出库
     * @DesignIdea: 新增智能分析串料信息，生成打印串料形式单据
     * @Author: 徐一贺
     * @CreateDate: 2020/6/23 9:47
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Throw:
     * @Version: v 3.5.1
     */
    @Transactional(rollbackFor = Exception.class)
    public JsonResult createRequestMaterial(JOutStorage jOutStorage) {
        //验证
        JsonResult jsonResult = new JsonResult();
        List<String> result = new ArrayList<>();
        for (int i = 0; i < jOutStorage.getInsertData().size(); i++) {
            if (jOutStorage.getInsertData().get(i).getOdaNum() == null || jOutStorage.getInsertData().get(i).getOdaNum() == 0) {
                result.add("\n第" + (i + 1) + "行" + " 数量为空 为空<br>");
            } else if (jOutStorage.getInsertData().get(i).getOdaNum() <= 0) {
                result.add("\n第" + (i + 1) + "行" + " 数量必须大于0 数量<br>");
            } else if (jOutStorage.getInsertData().get(i).getOdaNum() > storageOutDao.findByPrimaryKey(jOutStorage.getInsertData().get(i).getItyId()).getItyAvaNum()) {
                result.add("\n第" + (i + 1) + "行" + " 数量大于库存可用数量 数量<br>");
            }
        }
        if (result.size() == 0) {
            List<JStorageDetail> recordList = new ArrayList<>();
            for (int i = 0; i < jOutStorage.getInsertData().size(); i++) {
                boolean exist = false;
                for (int j = 0; j < recordList.size(); j++) {
                    if (recordList.get(j).getItyId().equals(jOutStorage.getInsertData().get(i).getItyId())) {
                        exist = true;
                        recordList.get(j).setOdaNum(recordList.get(j).getOdaNum() + jOutStorage.getInsertData().get(i).getOdaNum());
                        if (recordList.get(j).getOdaNum() > storageOutDao.findByPrimaryKey(recordList.get(j).getItyId()).getItyAvaNum()) {
                            List<Integer> errorList = recordList.get(j).getErrorLineNumlist();
                            errorList.add(i + 1);
                            recordList.get(j).setErrorLineNumlist(errorList);
                        }
                    }
                }
                if (exist == false) {
                    com.zhongwang.mms.module.jiaGongStorage.model.JStorageDetail obj = jOutStorage.getInsertData().get(i);
                    obj.getErrorLineNumlist().add(i + 1);
                    recordList.add(obj);
                }
            }
            for (int i = 0; i < recordList.size(); i++) {
                Double avaNum = storageOutDao.findByPrimaryKey(recordList.get(i).getItyId()).getItyAvaNum();
                if (recordList.get(i).getErrorLineNumlist().size() > 1) {
                    result.add("\n第" + (recordList.get(i).getErrorLineNumlist().toString()) + "行" + " 是一个库存其出库数之和大于库存可用量，无法出库,当前物料库存可用数量为【" + new BigDecimal(avaNum) + "】 数量<br>");
                }
            }
        }
        if (result.size() > 0) {
            result.add("\n单据保存失败，请先维护以上出库信息！");
            jsonResult.setData(result);
            return jsonResult;
        }
        //创建主单数据
        JStorage jStorage = new JStorage();
        jStorage.setOdrCode(getOrderCode(4));
        jStorage.setOdrRemark(jOutStorage.getFormData().getOdrRemark());
        jStorage.setOdrTakePerson(jOutStorage.getFormData().getOdrTakePerson());
        jStorage.setOdrMakePersonId(ShiroUtils.getUser().getId());
        jStorage.setOdrChangeFlag(0);
        jStorage.setOdrType(2);
        jStorage.setOdrRedFlag(0);
        jStorage.setOdrDate(jOutStorage.getFormData().getOdrDate());
        jStorage.setOdrReqFlag(0);
        jStorage.setOdrMakeDate(new Date());
        jStorage.setOdrTakeWorkshopId(jOutStorage.getFormData().getOdrTakeWorkshopId());
        jStorage.setOdrOutType(2);
        storageInDao.insert(jStorage);
        Integer odrId = jStorage.getOdrId();

        try {
            //创建明细单
            for (com.zhongwang.mms.module.jiaGongStorage.model.JStorageDetail pOrderDetailModel : jOutStorage.getInsertData()) {
                JStorageInventory jStorageInventory = storageOutDao.findByPrimaryKey(pOrderDetailModel.getItyId());
                JStorageDetail jStorageDetail = new JStorageDetail();
                jStorageDetail.setOdaType(2);
                jStorageDetail.setOdaOdrId(odrId);
                jStorageDetail.setOdaRedFlag(0);
                jStorageDetail.setOdaMatCode(pOrderDetailModel.getOdaMatCode());
                jStorageDetail.setOdaSapCode(pOrderDetailModel.getOdaSapCode());
                jStorageDetail.setOdaMatDesc(pOrderDetailModel.getOdaMatDesc());
                jStorageDetail.setOdaNum(pOrderDetailModel.getOdaNum());
                jStorageDetail.setOdaNumUnit(pOrderDetailModel.getOdaNumUnit());
//                jStorageDetail.setOdaTotalPrice(jStorageInventory.getItyPrice() * pOrderDetailModel.getOdaNum());//金额
//                jStorageDetail.setOdaNumPrice(jStorageInventory.getItyPrice());//单价
                jStorageDetail.setOdaTrackCode(pOrderDetailModel.getOdaTrackCode());
                jStorageDetail.setOdaProName(pOrderDetailModel.getOdaProName());
                jStorageDetail.setOdaProCode(pOrderDetailModel.getOdaProCode());
                jStorageDetail.setOdaPosition(pOrderDetailModel.getOdaPosition());
                jStorageDetail.setOdaTakeType(pOrderDetailModel.getOdaTakeType());
                if (pOrderDetailModel.getOdaBookkeepingDate() != null) {
                    jStorageDetail.setOdaBookkeepingDate(new SimpleDateFormat("yyyy-MM-dd").parse(pOrderDetailModel.getOdaBookkeepingDateWeb().replace('.', '-')));
                }
                jStorageDetail.setOdaSpec(pOrderDetailModel.getOdaSpec());
                jStorageDetail.setOdaOutItyId(pOrderDetailModel.getItyId());
                jStorageDetail.setOdaStockType(jStorageInventory.getItyStockType());
                jStorageDetail.setOdaRemarkType(pOrderDetailModel.getOdaRemarkType());
                jStorageDetail.setSupplier(pOrderDetailModel.getSupplier());//供应商
                jStorageDetail.setContractNo(pOrderDetailModel.getContractNo());//合同编号
                storageInDao.insertTStorageDetail(jStorageDetail);
                JStorageInventory changeNum = new JStorageInventory();
                changeNum.setItyId(pOrderDetailModel.getItyId());
                changeNum.setItyNum(jStorageInventory.getItyNum() - pOrderDetailModel.getOdaNum());
                Double avaNum = jStorageInventory.getItyAvaNum() - pOrderDetailModel.getOdaNum();
                if (avaNum < 0) {
                    avaNum = 0d;
                }
                changeNum.setItyAvaNum(avaNum);
                if(changeNum.getItyNum()<0 || changeNum.getItyAvaNum()<0){
                    Exception exception =  new Exception();
                    throw exception;
                }
               if(storageOutDao.updatePInventoryNumPrimaryKey(changeNum)==0){
                   Exception exception =  new Exception();
                   throw exception;
               }
            }
            AllocationResaultModel allocationResaultModel = new AllocationResaultModel();
            allocationResaultModel.setIsChangeFlag(0);
            //其中过程中所有库存信息中的数量不可被调整
            allocationResaultModel.setMessage("单据保存成功！");
            jsonResult.setData(allocationResaultModel);
            //记录操作日志
            logService.saveLog("出入库操作-领料出库", "出库单据编码：" + jStorage.getOdrCode());
        } catch (Exception ex) {
            //记录异常错误日志信息
            log.error("【领料出库-异常日志】:异常出库单编码：" + jStorage.getOdrCode() + "{" + ex.getMessage() + "}");
            jsonResult.setMsg("单据保存失败,请检查出库库存的数量是否充足！");
        }
        return jsonResult;
    }

    /**
     * @FunctionName: findAncestorChangeData
     * @Description: 根据子孙ID 获取串料历史中始祖的信息，并获取始祖信息时的库存数量
     * @DesignIdea: 使用递归获取始祖库存ID，并返回当前信息的始祖库存信息
     * @Author: 徐一贺
     * @CreateDate: 2020/6/29 9:47
     * @Phone: 18241927380
     * @Param: [ceoNeedItyId] 需求库存ID
     * @Return: [PInventoryModel]检索到的库存信息
     * @Throw:
     * @Version: v 1.0.0
     */
    public PInventoryModel findAncestorChangeData(Integer ceoNeedItyId) {
        PInventoryModel result = purPInventoryDao.getInventoryByPrimaryKey(ceoNeedItyId);
        PChangeOrderModel currentModel = new PChangeOrderModel();
        currentModel.setCeoNeedItyId(ceoNeedItyId);
        while (true) {
            if (currentModel != null) {
                currentModel = purChangeDao.getChangeCountByCeoNeedItyId(currentModel.getCeoNeedItyId());
            }
            if (currentModel != null) {
                result = purPInventoryDao.getInventoryByPrimaryKey(currentModel.getCeoUseItyId());
                currentModel = purChangeDao.getChangeCountByCeoNeedItyId(currentModel.getCeoUseItyId());
            } else {
                break;
            }
        }
        return result;
    }

    /**
     * 过去数量之和
     * 如果是成本中心的加上串料数量
     * @return
     */
    public Double getChangePInventoryAllNum(PInventory pInventory) {
        List<PChangeOrder> useChangeOrderList = purChangeDao.findPChangeOrderListByCeoUseItyIdAndCeoApplyStatus(pInventory.getItyId());
        if (useChangeOrderList.size() > 0) {
            for (PChangeOrder pChangeOrder : useChangeOrderList) {
                PInventory child = purChangeDao.getInventoryPrimaryKey(pChangeOrder.getCeoNeedItyId());
                if (child.getItyStockType().equals(2) || tCostDao.getTCostByCosProCode(child.getItyProCode())!=null) {
                    pInventory.setItyNum(pInventory.getItyNum() + getChangePInventoryAllNum(child));
                } else {
                    pInventory.setItyNum(pInventory.getItyNum() + getChangePInventoryAllNum(child) - child.getItyNum());
                }
            }
        }
        return pInventory.getItyNum();
    }

    /**
     * @FunctionName: getChangeOrderInvCount
     * @Description: 获取已执行的和已出库库存信息，获取其数量进行相加
     * @DesignIdea: 默认认为只串一次料
     * @Author: 徐一贺
     * @CreateDate: 2020/6/29 13:32
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Throw:
     * @Version: v 1.0.0
     */
    private Double getChangeOrderInvCount(Integer ceoUseItyId) {
        Double result = 0d;
        //获取根节点列表
        List<PChangeOrderModel> pChangeOrderModelList = purChangeDao.findPChangeOrderListByCeoUseItyId(ceoUseItyId);
        for (PChangeOrderModel pChangeOrderModel : pChangeOrderModelList) {
            PInventoryModel pInvModel = purPInventoryDao.getInventoryByPrimaryKey(pChangeOrderModel.getCeoNeedItyId());
            result += pInvModel.getItyNum();
        }
        return result;
    }

    /**
     * getPInventoryByPrimaryKey
     * 根据主键获取库存信息
     *
     * @param ityId
     * @return
     */
    public JStorageInventory getPInventoryByPrimaryKey(Integer ityId) {
        return storageOutDao.getPInventoryByPK(ityId);
    }
}